#include <iostream>
using std::cout;
using std::endl;

class Singleton
{
public:
    static Singleton * getInstance()
    {
        if(nullptr == _pInstance){
            _pInstance = new Singleton(1,2);
        }
        return _pInstance;
    }

    // static void destroy(){
    //     if(_pInstance){
    //         delete _pInstance;
    //         _pInstance = nullptr;
    //     }
    // }

    void init(int x,int y)
    {
        _ix = x;
        _iy = y;
    }
 
    void print() const
    {
        cout << "(" << _ix
            << "," << _iy
            << ")" << endl;
    }
    
private:
    class AutoRelease{
    public:
        ~AutoRelease()
        {
            if(_pInstance){
                delete _pInstance;
                _pInstance = nullptr;
            }

            // 保证destory函数一定会被自动调用
            // destroy();
        }
    };

    Singleton() = default;
    Singleton(const Singleton &) = delete;
    Singleton & operator=(const Singleton &) = delete;

    Singleton(int x,int y)
    : _ix(x)
    , _iy(y)
    {
        cout << "Singleton(int,int)" << endl;
    }
    
    ~Singleton()
    {
        cout << "~Singleton()" << endl;
    }

private:
    int _ix;
    int _iy;
    static Singleton * _pInstance;
    static AutoRelease _ar; // 静态对象成员 创建在全局静态区
};
Singleton * Singleton::_pInstance = nullptr;
Singleton::AutoRelease Singleton::_ar;

void test0(){
    Singleton * p1 = Singleton::getInstance();
    p1->init(100,200);
    p1->print();

    //如果是一个普通的Singeleton*指针
    //不能在Singleton类外调用私有的析构函数
    /* delete p1; */
    /* Singleton::destroy(); */
}

#if 0
void test1()
{
    //仍然要注意不能使用多个AutoRelease对象管理堆上的单例对象
    //否则也会发生double free问题
    // AutoRelease ar(Singleton::getInstance());
    // AutoRelease ar2(Singleton::getInstance());

    Singleton::getInstance()->init(100,200);
    Singleton::getInstance()->print();
    Singleton::getInstance()->init(10,20);
    Singleton::getInstance()->print();
    //不能手动调用destroy，会导致double free
    /* Singleton::destroy(); */
}
#endif

void test2(){
    Singleton::getInstance()->init(100,200);
    Singleton::getInstance()->print();
    Singleton::getInstance()->init(10,20);
    Singleton::getInstance()->print();
}

int main(void){
    test2();
    return 0;
}
